/**
 * @author: Files Controller
 * @author: YoungYa
 * @date: 2024-11-17 17:49:53
 */
import {
  BadRequestException,
  Controller,
  Post,
  UploadedFile,
  UseGuards,
  UseInterceptors,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiBearerAuth, ApiBody, ApiConsumes, ApiHeader, ApiTags } from '@nestjs/swagger'; // swagger 接口文档
import * as OSS from 'ali-oss'; // oss sdk
import { randomUUID } from 'crypto'; // 随机 uuid
import * as fs from 'fs';
import * as moment from 'moment'; // 时间插件 moment
import { diskStorage } from 'multer';
import { normalize } from 'path';
import * as xlsx from 'xlsx';

import App_configuration from '@/config/configuration'; // 全局配置
import { responseMessage } from '@/utils';
import { Logger } from '@/utils/log4js';
import type { Response } from '@/utils/types';

import { UploadFileDto } from './dto';

@ApiTags('文件上传')
@ApiHeader({
  name: 'Authorization',
  required: true,
  description: 'token令牌',
})
@ApiBearerAuth()
@Controller('upload')
export class FilesController {
  ossClient: OSS;
  constructor() {
    // 阿里云 bucket配置
    this.ossClient = new OSS(App_configuration().oss);
  }

  /**
   * @description: 上传单个文件
   * @author: YoungYa
   */
  @UseGuards(AuthGuard('jwt'))
  @UseInterceptors(FileInterceptor('file'))
  @Post('single-file')
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    description: '单个文件上传',
    type: UploadFileDto,
  })
  uploadFile(@UploadedFile() file: Express.Multer.File): Response<Express.Multer.File> {
    file.path = `http://${process.env.APP_HOST}:${
      process.env.APP_PROT
    }/static${file.path.replace(/\\/g, '/').replace(/upload/g, '')}`;
    return responseMessage(file);
  }

  /**
   * @description: 阿里云 oss 上传
   * @author: YoungYa
   */
  @UseGuards(AuthGuard('jwt'))
  @Post('single-file-oss')
  @UseInterceptors(
    FileInterceptor('file', {
      storage: diskStorage({
        filename: (req, file, cb) => {
          const filename = `${randomUUID()}.${file.mimetype.split('/')[1]}`;
          return cb(null, filename);
        },
      }),
    }),
  )
  async oos(@UploadedFile() file: Express.Multer.File): Promise<Response<Express.Multer.File>> {
    // 上传的时候我们运行你上传到内存中 然后发送给第三方但是这样做不好，
    // 如果存储文件太多或者并非量 你的机器会撑不住，因此我们建议的做法是先存到某
    // 临时目录，然后调用第三方去upload 最后由定时job删除这个up目录就好了
    // 主要还是文件的上传和下载 上传比较简单
    const result = await this.ossClient.put(
      `/upload/${moment().format('YYYYMMDD')}/${file.filename}`,
      normalize(file.path),
    );
    return responseMessage(result);
  }

  @UseGuards(AuthGuard('jwt'))
  @UseInterceptors(FileInterceptor('file'))
  @Post('excel')
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    description: 'excel文件上传',
    type: UploadFileDto,
  })
  async uploadExcel(@UploadedFile() file: Express.Multer.File) {
    if (!file) {
      throw new BadRequestException('请上传一个 Excel 文件');
    }

    // 检查文件类型
    const allowedMimeTypes = [
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'application/vnd.ms-excel',
    ];

    if (!allowedMimeTypes.includes(file.mimetype)) {
      throw new BadRequestException('上传的文件格式不正确，请上传 Excel 文件');
    }
    // 读取 Excel 文件
    const workbook = xlsx.readFile(file.path);

    // 检查工作表名称
    const sheetNames = workbook.SheetNames;
    if (!sheetNames || sheetNames.length === 0) {
      throw new BadRequestException('上传的 Excel 文件中没有工作表');
    }

    const sheetName = sheetNames[0];
    const worksheet = workbook.Sheets[sheetName];

    if (!worksheet) {
      throw new BadRequestException('无法读取工作表');
    }

    // 将数据转换为 JSON 数组
    const data = xlsx.utils.sheet_to_json(worksheet);
    // 处理完数据后，删除文件
    try {
      fs.unlinkSync(file.path); // 删除文件
      Logger.info(`文件已删除: ${file.path}`);
    } catch (err) {
      Logger.error(`删除文件时出错: ${err}`);
    }

    return {
      message: '文件上传成功',
      data,
    };
  }
}
